package kim.sesame.util.sensitive.interceptor;

import kim.sesame.util.sensitive.sensitive.Insensitive;
import kim.sesame.util.sensitive.sensitive.SensitiveTypeEnum;
import kim.sesame.util.sensitive.sensitive.Sensitivity;
import kim.sesame.util.sensitive.utils.DesensitizedUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * 数据更新拦截器
 */
@Intercepts({@Signature(
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class}
)})
public class PrivacyInputInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        Object parameter = args[1];
        if (parameter instanceof Map) {
            Map<?, ?> params = (Map)parameter;
            for (Object param : params.values()) {
                desensitize(param);
            }
        } else {
            desensitize(parameter);
        }

        return invocation.proceed();
    }


    private void desensitize(Object parameter) throws Exception {
        if (parameter != null && parameter.getClass().isAnnotationPresent(Sensitivity.class)) {
            desensitize(parameter, parameter.getClass());
        }

    }

    private void desensitize(Object parameter, Class<?> clazz) throws Exception {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Insensitive.class)) {
                Insensitive ins = field.getAnnotation(Insensitive.class);
                field.setAccessible(true);
                if (!"".equals(ins.srcField()) && !field.getName().equals(ins.srcField())) {
                    String srcVal = (String) getFieldValue(parameter, ins.srcField());
                    if (srcVal != null && !"".equals(srcVal)) {
                        String val = desensitize(srcVal, ins.type());
                        field.set(parameter, val);
                    }
                }
            } else if (field.getType().isAnnotationPresent(Sensitivity.class)) {
                field.setAccessible(true);
                desensitize(field.get(parameter));
            }
        }


    }



    private static Object getFieldValue(Object bean, String fieldName) throws Exception {
        Field field = bean.getClass().getDeclaredField(fieldName);
        if (field != null) {
            field.setAccessible(true);
            return field.get(bean);
        } else {
            return null;
        }
    }

    /**
     * 脱敏
     * @param origin 原值
     * @param type 类型
     * @return 脱敏值
     */
    private String desensitize(String origin,SensitiveTypeEnum type){
        switch (type) {
            case CHINESE_NAME:
                return DesensitizedUtils.chineseName(origin);
            case MERCHANT_NAME:
                return DesensitizedUtils.merchantName(origin);
            case ID_CARD:
                return DesensitizedUtils.idCardNum(origin);
            case FIXED_PHONE:
                return DesensitizedUtils.fixedPhone(origin);
            case MOBILE_PHONE:
                return DesensitizedUtils.mobilePhone(origin);
            case BANK_CARD:
                return DesensitizedUtils.bankCard(origin);
            case EMAIL:
                return DesensitizedUtils.email(origin);
            case ADDRESS:
                return DesensitizedUtils.address(origin);
            default:
                return null;
        }
    }
}
